home *** CD-ROM | disk | FTP | other *** search
- //
- // keyboard.cpp - implementation for class Keyboard
- // Author - Robin W. McKean
- // Last Update - February 21,1991
- // Copyright (C) 1991 All rights reserved
- //
- // This file remains the property of the author, Robin W. McKean. You are
- // free to use and change it as you see fit. This module, nor its object
- // code, may not however be included in any packaged software without the
- // written consent of the author.
- //
-
- // Contents ----------------------------------------------------------------
- //
- // Keyboard::Keyboard
- // Keyboard::isA
- // Keyboard::nameOf
- // Keyboard::processA
- // Keyboard::pollDevice
- //
- // Description
- //
- // Defines the class Keyboard. The purpose of this class is to input
- // information from the keyboard, tranlate that into an event and pass
- // it back to the user for processing.
- //
- // End ---------------------------------------------------------------------
-
- // Interface dependencies --------------------------------------------------
-
- #ifndef _IOSTREAM_H
- #include <iostream.h>
- #endif
-
- #ifndef _USETYPES_H
- #include <usetypes.h>
- #endif
-
- #ifndef _GEN_H
- #include <gen.h>
- #endif
-
- #ifndef _EVENT_H
- #include <event.h>
- #endif
-
- #ifndef _KEYBOARD_H
- #include <keyboard.h>
- #endif
-
- // End Interface dependencies ----------------------------------------------
-
- // Implementation dependencies ---------------------------------------------
-
- #ifndef _DOS_H
- #define _DOS_H
- #include <dos.h>
- #endif
-
- #ifndef _CONIO_H
- #define _CONIO_H
- #include <conio.h>
- #endif
-
- // End Implementation dependencies -----------------------------------------
-
- unsigned readKey( unsigned char enhancedBIOS );
-
- // Member Function //
-
- Keyboard::Keyboard( int initStatus ) : Device( initStatus )
-
- // Summary ------------------------------------------------------------------
- //
- // Sets the initial status of the keyboard, and resets the control
- // break function
- //
- // End ---------------------------------------------------------------------
- {
- type = D_KEYBOARD; // Set the keyboard type
- enhancedBIOS = 0; // Set default state of enhanced BIOS
-
- REGS regs; // Check for enhanced BIOS
-
- regs.h.ah = 5;
- regs.x.cx = 0xffff;
- int86( 0x16, ®s, ®s );
-
- // AL = 0 if enhanced BIOS are present
- if( regs.h.al == 0 )
- enhancedBIOS = 0x10;
- else
- enhancedBIOS = 0;
-
- // Now, lets get the control break status, and reset it with ours
- regs.h.ah = 0x33;
- regs.h.al = 0;
- int86( 0x21, ®s, ®s );
-
- breakStatus = regs.h.dl; // Save the current break status
-
- // Now disable control break
- regs.h.ah = 0x33;
- regs.h.al = 1;
- regs.h.dl = 0;
- int86( 0x21, ®s, ®s );
-
- altKeyStatus = 0;
- }
-
- // End Keyboard::Keyboard //
-
- // Member Function //
-
- #pragma argsused
- Keyboard::Keyboard( Keyboard& theDevice )
-
- // Description -------------------------------------------------------------
- //
- // Copies one Keyboard into another
- //
- // Parameters
- //
- // Device&
- //
- // The Keyboard to be copied
- //
- // End ---------------------------------------------------------------------
- {
- }
-
- // End Keyboard::Keyboard //
-
- // Member Function
-
- Keyboard::~Keyboard( )
- {
- // Reset the control break status
- REGS regs;
-
- regs.h.ah = 0x33;
- regs.h.al = 1;
- regs.h.dl = breakStatus;
- int86( 0x21, ®s, ®s );
- }
- // Keyboard::~Keyboard //
-
- // Member Function //
-
- classType Keyboard::isA( ) const
-
- // Description -------------------------------------------------------------
- //
- // Returns a value representation of a class
- //
- // End ---------------------------------------------------------------------
- {
- return keyboardClass;
- }
-
- // End Keyboard::isA( ) //
-
- // Member Function //
-
- char *Keyboard::nameOf( ) const
-
- // Description -------------------------------------------------------------
- //
- // Returns a character representation of a class
- //
- // End ---------------------------------------------------------------------
- {
- return "Keyboard";
- }
-
- // End Keyboard::nameOf //
-
- // Member Function
-
- void Keyboard::pollDevice( )
-
- // Description -------------------------------------------------------------
- //
- // Reads the keyboard if a keystroke is waiting. It then builds an
- // event from the keystroke and the key shift state. If the keyboard
- // status is D_ON, it puts the key into the EventManagers queue.
- //
- // End ---------------------------------------------------------------------
-
- {
- REGS regs;
-
- unsigned int key = 0;
- unsigned int shiftKey;
-
- // Read the current shift state first
- regs.h.ah = 2;
- int86( 0x16, ®s, ®s );
-
- // Shift key status stored in AL
- shiftKey = ( unsigned )regs.h.al;
- int newAltKey = ( int ) shiftKey & K_ALT;
-
- // Check to see if there is a keystroke waiting
- if( !kbhit( ) )
- {
- // No keystroke, now check to see if Alt key status has changed
- if( altKeyStatus && !newAltKey )
- {
- altKeyStatus = 0; // Alt key was pressed, now released
- key = ALT_KEY_PRESSED; // Translate into F10
- }
- else
- {
- altKeyStatus = newAltKey; // Change the alt key status to
- newAltKey = 0; // current status
- }
- }
-
- // We know there is a key stroke waiting, so fetch it
- else
- {
- key = readKey( enhancedBIOS );
- altKeyStatus = 0;
- }
-
- // If there was something in key, than build an event,
- // but not if the keyboard is disabled
- if( key && status == D_ON )
- {
- Event event;
- event.type = E_KEY;
- event.typeCode = key;
- event.shiftState = shiftKey;
- if( theEventManager ) theEventManager->putEvent( event, FALSE );
- }
- }
-
- int Keyboard::processA( Event& theEvent )
- {
- if( theEvent.type == S_DEVICE && status != D_INACTIVE )
- {
- switch( theEvent.type )
- {
- case D_OFF:
- case D_ON:
- status = theEvent.type;
- break;
- }
- }
- return( 0 );
- }
-
- // This is a function that I use to read the keyboard. It comes from
- // the MicroSoft QuickC compiler, with some few adjustments I have made
-
- #pragma argsused
- unsigned readKey( unsigned char enhancedBIOS )
- {
- unsigned iKey, iShiftstatus;
-
- // Get key code.
- _AH = enhancedBIOS; // Non-portable code!
- geninterrupt( 0x16 );
-
- iKey = _AX; // Non-portable code!
-
- iShiftstatus = ( unsigned )*( ( unsigned char far * ) 0x417L ) & 0x0f;
-
- // If low byte is not zero, it's an ASCII key. Check scan code to see
- // if it's on the numeric keypad. If not, clear high byte and return.
-
- if( iKey & 0x00ff )
- if( (iKey >> 8) < 69 ) {
- iKey = ( iKey & 0x00ff );
- iShiftstatus &= 0x000f;
- switch( iShiftstatus ) {
- case 4:
- return( 0x0500 | iKey ); // Control ( 5 )
- case 8:
- return( 0x0600 | iKey ); // Alt ( 6 )
- default:
- return( 0x0000 | iKey );
- }
- }
-
- // For function keys and numeric keypad, put scan code in low byte
- // and shift state codes in high byte.
- iKey >>= 8;
- iShiftstatus &= 0x000f;
- switch( iShiftstatus )
- {
- case 0:
- return( 0x0100 | iKey ); // None (1)
- case 1:
- case 2:
- case 3:
- return( 0x0200 | iKey ); // Shift (2)
- case 4:
- return( 0x0300 | iKey ); // Control (3)
- case 8:
- return( 0x0400 | iKey ); // Alt (4)
- }
- return( 0 );
- }
-